﻿using HDJ.Framework.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

public class StateMachineData<S, T> where S : StateDataBase, new() where T : StateTransitionDataBase, new()
{
    public List<S> stateDataList = new List<S>();
    public List<T> transitionDataList = new List<T>();

    public CallBack<S> AddStateEvent;
    public CallBack<S> DeleteStateEvent;
    public CallBack<T> AddTransitionEvent;
    public CallBack<T> DeleteTransitionEvent;
    
    public void AddState(S s)
    {
        if (s == null)
            return;
        if (GetState(s.id) != null)
        {
            s.id = GetMaxStateIDFromList() + 1;
        }
        stateDataList.Add(s);

        if (AddStateEvent != null)
        {
            AddStateEvent(s);
        }
    }
    public void AddState(Vector2 pos = new Vector2(), string name = "New State")
    {
        int id = GetMaxStateIDFromList() + 1;
        S s = new S();
        s.id = id;
        s.editorPosition = pos;
        s.name = name;

        stateDataList.Add(s);

        if (AddStateEvent != null)
        {
            AddStateEvent(s);
        }
    }

    public void DeleteState(int id)
    {
        S s = GetState(id);
        if (s != null)
        {
            int count = s.transitionFromStateIDs.Count;
            List<int> list = new List<int>(s.transitionFromStateIDs);
            for (int i = 0; i < count; i++)
            {
                int tID = list[i];
                DeleteTransition(tID);

            }
            count = s.transitionToStateIDs.Count;
            list.Clear();
            list.AddRange(s.transitionToStateIDs);
            for (int i = 0; i < count; i++)
            {
                int tID = list[i];
                DeleteTransition(tID);
            }
            stateDataList.Remove(s);
            if (DeleteStateEvent != null)
            {
                DeleteStateEvent(s);
            }
        }
    }

    public void AddTransition(int fromStateID, int toStateID)
    {
        int id = GetMaxTransitionIDFromList() + 1;
        T t = new T();
        t.transitionID = id;
        t.fromStateID = fromStateID;
        t.toStateID = toStateID;
        S s = GetState(fromStateID);
        s.transitionToStateIDs.Add(id);
        S s1 = GetState(toStateID);
        s1.transitionFromStateIDs.Add(id);
        transitionDataList.Add(t);
        if (AddTransitionEvent != null)
        {
            AddTransitionEvent(t);
        }
    }
    public void DeleteTransitions(List<T> ts)
    {

        for (int i = 0; i < ts.Count; i++)
        {
            //Debug.Log("DeleteTransitions  transitionID: " + ts[i].transitionID);
            DeleteTransition(ts[i].transitionID);
        }
    }
    public void DeleteTransition(int transitionID)
    {
        T t = GetTransition(transitionID);
        if (t != null)
        {
            S s = GetState(t.fromStateID);
            if (s != null)
            {
                if (s.transitionToStateIDs.Contains(transitionID))
                    s.transitionToStateIDs.Remove(transitionID);
            }
            S s1 = GetState(t.toStateID);
            if (s1 != null)
            {
                if (s1.transitionFromStateIDs.Contains(transitionID))
                    s1.transitionFromStateIDs.Remove(transitionID);
            }
            transitionDataList.Remove(t);
            if (DeleteTransitionEvent != null)
            {
                DeleteTransitionEvent(t);
            }
        }
    }

    public void Clear()
    {
        for (int i = 0; i < stateDataList.Count; i++)
        {
            S s = stateDataList[i];
            DeleteState(s.id);
        }

        stateDataList.Clear();
    }

    public S GetState(int id)
    {
        for (int i = 0; i < stateDataList.Count; i++)
        {
            S s = stateDataList[i];
            if (s.id == id)
                return s;
        }

        return null;
    }
    public T GetTransition(int transitionID)
    {
        for (int i = 0; i < transitionDataList.Count; i++)
        {
            T t = transitionDataList[i];
            if (t.transitionID == transitionID)
                return t;
        }

        return null;
    }
    /// <summary>
    /// 获取从某状态到某状态的全部Transition
    /// </summary>
    /// <param name="fromStateID"></param>
    /// <param name="toStateID"></param>
    /// <returns></returns>
    public T[] GetTransitions(int fromStateID, int toStateID)
    {
        List<T> list = new List<T>();
        for (int i = 0; i < transitionDataList.Count; i++)
        {
            T t = transitionDataList[i];
            if (t.fromStateID == fromStateID && t.toStateID == toStateID)
                list.Add(t);
        }
        return list.ToArray();
    }

    public List<S> GetChildState(S s)
    {
        List<S> list = new List<S>();
        for (int i = 0; i < s.transitionToStateIDs.Count; i++)
        {
            T t = GetTransition(s.transitionToStateIDs[i]);
            S temp = GetState(t.toStateID);
            if (!list.Contains(temp))
                list.Add(temp);
        }
        return list;
    }
    private int GetMaxStateIDFromList()
    {
        int max = -1;
        for (int i = 0; i < stateDataList.Count; i++)
        {
            S s = stateDataList[i];
            if (s.id > max)
                max = s.id;
        }

        return max;
    }

    private int GetMaxTransitionIDFromList()
    {
        int max = -1;
        for (int i = 0; i < transitionDataList.Count; i++)
        {
            T t = transitionDataList[i];
            if (t.transitionID > max)
                max = t.transitionID;
        }

        return max;
    }
}

